import React, {useState, useEffect} from 'react'
declare type Func<T = {}> = (value?: T) => void
type SetStateFunc<T> = (preState?: T) => T
export interface WithShareStateProps<T> {
  shareState: [T, Func<T>]
}

export function WithShareState<T extends object>(defaultValue: T) {
  let shareValue = defaultValue

  const listeners = new Set<Func<T>>()
  const addListener = (listener: Func<T>) => {
    listeners.add(listener)
    //添加监听 默认调用一次
    // listener(shareValue)
  }
  const removeListener = (listener: Func<T>) => listeners.delete(listener)
  function setShareState(value: Partial<T> | SetStateFunc<Partial<T>>) {
    let newState: Partial<T>
    if (typeof value === 'function') {
      newState = (value as SetStateFunc<Partial<T>>)(shareValue)
    } else {
      newState = value
    }
    shareValue = {...shareValue, ...newState}
    listeners.forEach(setValue => {
      setValue && setValue(shareValue)
    })
  }

  function ShareStateComponent<P>(Component: React.ComponentType<P & WithShareStateProps<T>>) {
    const WithStoreComponent: React.FC<P> = props => {
      const [value, setValue] = useState(shareValue)
      useEffect(() => {
        addListener(setValue)
        return () => removeListener(setValue)
      }, [])
      return <Component {...props} shareState={[shareValue, setShareState]} />
    }
    return WithStoreComponent
  }
  function useShareState(): [T, Func<Partial<T> | SetStateFunc<Partial<T>>>] {
    let [state, setState] = useState(shareValue)
    useEffect(() => {
      addListener(setState)
      return () => removeListener(setState)
    }, [])
    return [shareValue, setShareState]
  }
  ShareStateComponent.useShareState = useShareState
  ShareStateComponent.setShareState = setShareState
  ShareStateComponent.addListener = addListener
  ShareStateComponent.removeListener = removeListener
  ShareStateComponent.getShareState = () => shareValue
  return ShareStateComponent
}
